package com.gitee.dictionary.base.impl;

import com.gitee.dictionary.base.BaseDictionaryEnum;
import com.gitee.dictionary.base.HandleDictionaryEnums;
import com.gitee.dictionary.exception.DictionaryCodeCheckException;
import com.gitee.dictionary.properties.DictionaryEnumProperties;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author <a href="mailto:lin-mt@outlook.com">lin-mt</a>
 */
public class DefaultHandleDictionaryEnumsImpl<T extends BaseDictionaryEnum> implements HandleDictionaryEnums<T> {
    
    private final Logger logger = LoggerFactory.getLogger(DefaultHandleDictionaryEnumsImpl.class);
    
    private final DictionaryEnumProperties dictionaryEnumProperties;
    
    public DefaultHandleDictionaryEnumsImpl(@NonNull DictionaryEnumProperties dictionaryEnumProperties) {
        this.dictionaryEnumProperties = dictionaryEnumProperties;
    }
    
    @Override
    public void handle(@NonNull Set<Class<T>> dictionaryEnums) {
        Map<String, Class<T>> allCode = new HashMap<>();
        for (Class<T> dictionaryEnum : dictionaryEnums) {
            if (dictionaryEnum.isEnum()) {
                BaseDictionaryEnum[] enumConstants = dictionaryEnum.getEnumConstants();
                for (BaseDictionaryEnum enumConstant : enumConstants) {
                    // 检查Code长度是否大于一层的长度
                    if (Strings.isBlank(enumConstant.getCode())
                            || enumConstant.getCode().length() < this.dictionaryEnumProperties.getOneLevelLength()) {
                        throw new DictionaryCodeCheckException(
                                String.format("%s(%s)：Code长度必须大于 %s", dictionaryEnum, enumConstant.getCode(),
                                        this.dictionaryEnumProperties.getOneLevelLength()));
                    }
                    // 检查Code的层数是否为一层长度的整数倍
                    if (enumConstant.getCode().length() % this.dictionaryEnumProperties.getOneLevelLength() != 0) {
                        throw new DictionaryCodeCheckException(
                                String.format("%s(%s)：Code长度必须是 %s 的整数倍", dictionaryEnum, enumConstant.getCode(),
                                        this.dictionaryEnumProperties.getOneLevelLength()));
                    }
                    // 检查Code层级是否大于最大值
                    if (enumConstant.getCode().length() / this.dictionaryEnumProperties.getOneLevelLength()
                            > this.dictionaryEnumProperties.getMaxLevelCount()) {
                        throw new DictionaryCodeCheckException(
                                String.format("%s(%s)：Code层级不能大于 %s", dictionaryEnum, enumConstant.getCode(),
                                        this.dictionaryEnumProperties.getMaxLevelCount()));
                    }
                    // 检查是否存在重复的Code
                    if (allCode.containsKey(enumConstant.getCode())) {
                        String duplicatedCodeMessage = String
                                .format("%s 与 %s 出现了重复的Code：%s, ", allCode.get(enumConstant.getCode()), dictionaryEnum,
                                        enumConstant.getCode());
                        switch (this.dictionaryEnumProperties.getDuplicated()) {
                            case EXCEPTION:
                                throw new DictionaryCodeCheckException(duplicatedCodeMessage);
                            case ERROR:
                                this.logger.error(duplicatedCodeMessage);
                                break;
                            case WARNING:
                                this.logger.warn(duplicatedCodeMessage);
                                break;
                            default:
                                // 默认值是抛出异常，不会为null，所以这里不处理
                                break;
                        }
                    } else {
                        allCode.put(enumConstant.getCode(), dictionaryEnum);
                    }
                }
            }
        }
    }
}
